リソースグループタグ付けAPIで自分が作成したリソースのみを定期的にメール通知してみた
はじめに
こんにちは、アノテーションのなかたです。
今回は、複数人にIAMロールが払い出されている検証アカウントでの環境において、自分のリソースのみを把握したいというのが背景になります。
リソースタグに自分の名前を付与し、Lambdaの定期実行でリソース情報をメール送信することで実現してみました。
今回の構成図は以下のとおりです。
背景
私のチームでは、検証アカウントでの環境において複数人にIAMロールが払い出されています。
つまり、他の人が作成したリソースが混在しています。
そのため、自分のリソースを把握するのが少し手間になっていました。
しかし、自分のリソースのみを把握する方法について、同期の岩橋さんが以下の運用方法を提案してくださいました。
- 作成したリソースに自分の名前が含まれたタグを付与する
- CLIで以下のコマンドを実行することで、サービスを横断的に検索し、指定されたタグのリソースを検出できる
aws resourcegroupstaggingapi get-resources --tag-filters Key=Owner,Values=自分の名前
こちらのコマンドを実行すると、以下のようにJSON形式でリソース情報が出力されます。
JSON以外の出力形式について
以上のコマンドでは、大量のリソースが表示された際に見づらく、他の形式の方が見やすいと思います。
そのため、他の形式でどのように出力されるかいくつかご紹介したいと思います。
こちらも岩橋さんから情報を提供して頂きました。
--output table
テキストでテーブル表記に出力できます。
-------------------------------------------------------------------------------------
| GetResources |
+-----------------------------------------------------------------------------------+
|| ResourceTagMappingList ||
|+---------------------------------------------------------------------------------+|
|| ResourceARN ||
|+---------------------------------------------------------------------------------+|
|| arn:aws:sns:ap-northeast-1:AWSアカウントID:aaaaaaaaaaaaaaaaaaaaaaaaaa ||
|+---------------------------------------------------------------------------------+|
||| Tags |||
||+------------------------------------+------------------------------------------+||
||| Key | Value |||
||+------------------------------------+------------------------------------------+||
||| Owner | 自分の名前 |||
||+------------------------------------+------------------------------------------+||
--output text
単純なテキスト形式の出力になります。
RESOURCETAGMAPPINGLIST arn:aws:ec2:ap-northeast-1:AWSアカウントID:launch-template/lt-111aaa222bbb333cc
TAGS Owner 自分の名前
--output yaml
yamlでの出力形式です。
ResourceTagMappingList:
- ResourceARN: arn:aws:sns:ap-northeast-1:AWSアカウントID:aaaaa
Tags:
- Key: Owner
Value: 自分の名前
jq
コマンドを使用した色付け
出力されたテキストに対して、jq
コマンドを使用して色付けができるようです。
この運用方法により自分のリソースを把握できるだけでなく、今まで記憶に頼って行っていたリソース削除の負担が軽減されました!
従来では、リソース作成とともにサービス名を記憶して、検証が終わったタイミングでそれらを思い出して削除していました。
現在は、リソース作成時にタグを付与し、検証が終わったタイミングでCLIコマンドを実行するだけで、削除するべきリソースを把握できます。
そのため、検証のみに脳のリソースを割くことができ、楽に検証を行えるようになりました!
今回は、こちらを定期実行することでリソース検出の自動化を行い、より楽できないかと考えて検証してみた記事になります。
やってみる
1. SNSトピックの作成
- SNSトピックを作成します
- 自分のメールアドレスをサブスクリプションに登録します
- 受信したメールからメールアドレスの認証します
- 作成したSNSトピックのARNをコピーします
2. Lambda関数の作成
- 以下のコードをデプロイします、こちらのスクリプトは、Claude 3.5 Sonnetを使用して作成しました。
import boto3
import json
import os
from datetime import datetime
# グローバル変数として設定情報を保持
OWNER_NAME = os.environ.get('OWNER_NAME')
SNS_TOPIC_ARN = os.environ.get('SNS_TOPIC_ARN')
def lambda_handler(event: dict, context: dict) -> dict:
if not OWNER_NAME or not SNS_TOPIC_ARN:
raise ValueError("OWNER_NAME and SNS_TOPIC_ARN must be set in environment variables")
# 1. リソース情報の取得
resources = get_tagged_resources(OWNER_NAME)
# 2. メッセージの作成
message = format_message(resources)
# 3. SNSトピックにメッセージを送信
send_sns_message(SNS_TOPIC_ARN, message)
return {"statusCode": 200, "body": "メッセージが正常に送信されました"}
def get_tagged_resources(owner_name: str) -> list[dict]:
client = boto3.client('resourcegroupstaggingapi')
response = client.get_resources(
TagFilters=[
{
'Key': 'Owner',
'Values': [owner_name]
}
]
)
return [
{
'name': resource.get('ResourceARN').split(':')[-1],
'service': resource.get('ResourceARN').split(':')[2],
'url': f"https://console.aws.amazon.com/resource-groups/resources/{resource.get('ResourceARN')}"
}
for resource in response.get('ResourceTagMappingList', [])
]
def format_message(resources: list[dict]) -> str:
message = f"🚀 こんにちは、{OWNER_NAME}さん!\n\n"
message += "現在、あなたが管理しているAWSリソースの最新情報をお届けします。\n"
message += "タグ付けされたリソース一覧:\n\n"
for resource in resources:
message += f"サービス: {resource['service']}\n"
message += f"名前: {resource['name']}\n"
message += f"URL: {resource['url']}\n\n"
return message
def send_sns_message(topic_arn: str, message: str) -> None:
sns_client = boto3.client('sns')
sns_client.publish(
TopicArn=topic_arn,
Message=message,
Subject="あなたのAWSリソース管理レポート"
)
- 環境変数を設定します
OWNER_NAME
: Ownerタグに付与している名前
SNS_TOPIC_ARN
: 先ほど作成したSNSトピックのARN - Lambdaのロールに以下のポリシーを追加します
AWSResourceGroupsReadOnlyAccess
sns:Publish
を許可するインラインポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "sns:Publish",
"Resource": "arn:aws:sns:region:account-id:topic-name"
}
]
}
- テストを実行し、メールの受信確認を行います
3. メールの確認
以下のようなメールを受信できました!
4. EventBridgeスケジュールの作成
無事メールを受信できたため、Lambda関数を定期実行させます。
退勤時間の少し前くらいに通知するのが適切かと考えたので、平日のみ毎日1回ずつ、17時ごろにスケジュールします。
次にcronでスケジュールを設定します。
EventBridge Schedulerのcron式は少し癖があり、ハマりました。
公式ドキュメントを参照しながら作成するのがおすすめです。
ターゲットAPIでAWS Lambda Invoke
を選択します。
作成したLambda関数を指定します。
ペイロード
コードが引数に依存していないため、適当なJSONを指定します。
{
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
オプションを設定します。
スケジュール完了後のアクション
でDELETE
を選択すると、最後の呼び出しが完了した際にスケジュールを削除できます。
今回は、特にそのような要件はないのでNONE
にしました。
また、必ず実行してほしいタスクではないので再試行ポリシー
をオフにしました。
設定情報を確認し、スケジュールを作成
ボタンを選択します。
スケジュールが作成されました!
こちらのスケジュールからLambda関数の実行も確認できました。
おわりに
EventBridge Schedulerについて、初めて使用しました。cron式の指定に苦労しましたが、Lambda関数の実行や様々なAWSサービスのAPI実行に対応していて、使いやすい印象がありました。
また、同期のかつまたさんが先日EventBridge Schedulerについて投稿されていたため、そちらもご覧ください。
参考
アノテーション株式会社について
アノテーション株式会社はクラスメソッドグループのオペレーション専門特化企業です。サポート・運用・開発保守・情シス・バックオフィスの専門チームが、最新 IT テクノロジー、高い技術力、蓄積されたノウハウをフル活用し、お客様の課題解決を行っています。当社は様々な職種でメンバーを募集しています。「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、アノテーション株式会社 採用サイトをぜひご覧ください。